#region Copyright 
/*-------------------------------------------------------------------------
* 命名空间名称/文件名:    SSPivot.Common.Extensions/CollectionExtensions 
* CLR版本:     4.0.30319.42000
* 机器名称:    DESKTOP-NHMLO8A
* 功 能：       集合扩展方法，提供对ICollection、IList等集合类型的扩展操作
* 类 名：       CollectionExtensions
* 创建时间：  2025/5/22 10:09:02
* 版本号：      v1.0
* 创建人:        xulong
*-------------------------------------------------------------------------*/
#endregion
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SSPivot.Common.Extensions
{
    public static class CollectionExtensions
    {
        /// <summary>
        /// 是否有值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static bool IsNullOrEmpty<T>([CanBeNull] this ICollection<T> source)
        {
            return source == null || source.Count <= 0;
        }
        /// <summary>
        /// 如果条件成立，添加项
        /// </summary>
        public static void AddIf<T>(this ICollection<T> collection, T value, bool flag)
        {
            Check.NotNullVoid(collection, nameof(collection));
            if (flag)
            {
                collection.Add(value);
            }
        }
        /// <summary>
        /// 如果条件成立，添加项
        /// </summary>
        public static void AddIf<T>(this ICollection<T> collection, T value, Func<bool> func)
        {
            Check.NotNullVoid(collection, nameof(collection));
            if (func())
            {
                collection.Add(value);
            }
        }

        /// <summary>
        /// 如果不存在，添加项
        /// </summary>
        public static void AddIfNotExist<T>(this ICollection<T> collection, T value, Func<T, bool> existFunc = null)
        {
            Check.NotNullVoid(collection, nameof(collection));
            bool exists = existFunc == null ? collection.Contains(value) : collection.Any(existFunc);
            if (!exists)
            {
                collection.Add(value);
            }
        }
        /// <summary>
        /// 如果不为空，添加项
        /// </summary>
        public static void AddIfNotNull<T>(this ICollection<T> collection, T value) where T : class
        {
            Check.NotNullVoid(collection, nameof(collection));
            if (value != null)
            {
                collection.Add(value);
            }
        }
        /// <summary>
        /// 获取对象，不存在对使用委托添加对象
        /// </summary>
        public static T GetOrAdd<T>(this ICollection<T> collection, Func<T, bool> selector, Func<T> factory)
        {
            Check.NotNullVoid(collection, nameof(collection));
            T item = collection.FirstOrDefault(selector);
            if (item == null)
            {
                item = factory();
                collection.Add(item);
            }

            return item;
        }

        /// <summary>
        /// 交换两项的位置
        /// </summary>
        public static void Swap<T>(this IList<T> list, int index1, int index2)
        {
            Check.Between(index1, nameof(index1), 0, list.Count, true);
            Check.Between(index2, nameof(index2), 0, list.Count, true);

            if (index1 == index2)
            {
                return;
            }

            T tmp = list[index1];
            list[index1] = list[index2];
            list[index2] = tmp;
        }
        /// <summary>
        /// 将指定项前移
        /// </summary>
        public static bool SwapUp<T>(this IList<T> list, T item)
        {
            Check.NotNullVoid(item, nameof(item));
            Check.NotNullVoid(list, nameof(list));

            if (list.Count <= 1)
            {
                return false;
            }

            int index = list.IndexOf(item);
            if (index == 0)
            {
                return false;
            }

            list.Swap(index, index - 1);
            return true;
        }
        /// <summary>
        /// 将指定项后移
        /// </summary>
        public static bool SwapDown<T>(this IList<T> list, T item)
        {
            Check.NotNullVoid(item, nameof(item));
            Check.NotNullVoid(list, nameof(list));

            if (list.Count <= 1)
            {
                return false;
            }

            int index = list.IndexOf(item);
            if (index == list.Count - 1)
            {
                return false;
            }

            list.Swap(index, index + 1);
            return true;
        }
        /// <summary>
        /// 从集合中删除满足给定<paramref name=“predicate”/>的所有项。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public static IList<T> RemoveAll<T>(this ICollection<T> source, Func<T, bool> predicate)
        {
            var items = source.Where(predicate).ToList();

            foreach (var item in items)
            {
                source.Remove(item);
            }

            return items;
        }
        /// <summary>
        /// 从集合中删除所有项目。
        /// </summary>
        /// <typeparam name="T">Type of the items in the collection</typeparam>
        /// <param name="source">The collection</param>
        /// <param name="items">Items to be removed from the list</param>
        public static void RemoveAll<T>(this ICollection<T> source, IEnumerable<T> items)
        {
            foreach (var item in items)
            {
                source.Remove(item);
            }
        }
        /// <summary>
        /// NameValueCollection扩展方法，用于将@this转换为字典。
        /// </summary>
        /// <param name="this">The @this to act on.</param>
        /// <returns>@this as an IDictionary&lt;string,object&gt;</returns>
        public static IDictionary<string, string> ToDictionary(this NameValueCollection @this)
        {
            var dict = new Dictionary<string, string>();

            if (@this != null)
            {
                foreach (var key in @this.AllKeys)
                {
                    dict.Add(key, @this[key]);
                }
            }

            return dict;
        }
         
        /// <summary>
        /// 向集合中添加多个元素
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="this">目标集合</param>
        /// <param name="values">要添加的元素数组</param>
        public static void AddRange<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, params T[] values)
        {
            if (@this.IsReadOnly)
            {
                return;
            }
            foreach (var value in values)
            {
                @this.Add(value);
            }
        }
         
        /// <summary>
        /// 根据条件向集合中添加多个元素
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="this">目标集合</param>
        /// <param name="predicate">添加条件判断函数</param>
        /// <param name="values">要添加的元素数组</param>
        public static void AddRangeIf<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, Func<T, bool> predicate, params T[] values)
        {
            if (@this.IsReadOnly) return;
            foreach (var value in values)
            {
                if (predicate(value))
                {
                    @this.Add(value);
                }
            }
        }
         
        /// <summary>
        /// 向集合中添加多个不重复的元素
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="this">目标集合</param>
        /// <param name="values">要添加的元素数组</param>
        public static void AddRangeIfNotContains<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, params T[] values)
        {
            if (@this.IsReadOnly) return;
            foreach (var value in values)
            {
                if (!@this.Contains(value))
                {
                    @this.Add(value);
                }
            }
        }
 
        /// <summary>
        /// 检查集合是否包含所有指定元素
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="this">目标集合</param>
        /// <param name="values">要检查的元素数组</param>
        /// <returns>如果包含所有元素返回true，否则返回false</returns>
        public static bool ContainsAll<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, params T[] values)
        {
            foreach (var value in values)
            {
                if (!@this.Contains(value))
                {
                    return false;
                }
            }

            return true;
        }

 
        /// <summary>
        /// 检查集合是否包含任意指定元素
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="this">目标集合</param>
        /// <param name="values">要检查的元素数组</param>
        /// <returns>如果包含任意元素返回true，否则返回false</returns>
        public static bool ContainsAny<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, params T[] values)
        {
            foreach (var value in values)
            {
                if (@this.Contains(value))
                {
                    return true;
                }
            }

            return false;
        }

         
        /// <summary>
        /// 检查集合是否非空
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="this">目标集合</param>
        /// <returns>如果集合非空返回true，否则返回false</returns>
        public static bool IsNotNullOrEmpty<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this)
        {
            return @this != null && @this.Count != 0;
        }

   
        public static void RemoveIf<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, T value, Func<T, bool> predicate)
        {
            if (@this.IsReadOnly) return;
            if (predicate(value))
            {
                @this.Remove(value);
            }
        }

    
        public static void RemoveIfContains<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, T value)
        {
            if (@this.IsReadOnly) return;
            if (@this.Contains(value))
            {
                @this.Remove(value);
            }
        }

 
        public static void RemoveRange<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, params T[] values)
        {
            foreach (var value in values)
            {
                @this.Remove(value);
            }
        }

 
        public static void RemoveRangeIf<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, Func<T, bool> predicate, params T[] values)
        {
            if (@this.IsReadOnly) return;
            foreach (var value in values)
            {
                if (predicate(value))
                {
                    @this.Remove(value);
                }
            }
        }
 
        public static void RemoveRangeIfContains<T>([JetBrains.Annotations.NotNull] this ICollection<T> @this, params T[] values)
        {
            if (@this.IsReadOnly) return;
            foreach (var value in values)
            {
                if (@this.Contains(value))
                {
                    @this.Remove(value);
                }
            }
        }
 
        public static void RemoveWhere<T>(this ICollection<T> @this, Func<T, bool> predicate)
        {
            if (@this.IsReadOnly) return;
            var list = @this.Where(predicate).ToList();
            foreach (var item in list)
            {
                @this.Remove(item);
            }
        }

 
        /// <summary>
        /// 获取集合的随机排序列表
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="list">目标集合</param>
        /// <returns>随机排序后的新列表</returns>
        /// <remarks>
        /// 使用Fisher-Yates洗牌算法变体实现随机排序
        /// </remarks>
        private static List<T> GetRandomList<T>([JetBrains.Annotations.NotNull] this IList<T> list)
        {
            return System.Linq.Enumerable.Range(0, list.Count).OrderBy(_ => new Random().Next(list.Count)).Select(i => list[i]).ToList();
        }
        /// <summary>
        /// 连接字符串集合中的所有字符串
        /// </summary>
        /// <param name="this">字符串集合</param>
        /// <returns>连接后的字符串</returns>
        public static string Concatenate([JetBrains.Annotations.NotNull] this IEnumerable<string> @this)
        {
            var sb = new StringBuilder();

            foreach (var s in @this)
            {
                sb.Append(s);
            }

            return sb.ToString();
        }

        /// <summary>
        /// 连接集合元素转换后的字符串
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="source">源集合</param>
        /// <param name="func">字符串转换函数</param>
        /// <returns>连接后的字符串</returns>
        public static string Concatenate<T>([JetBrains.Annotations.NotNull] this IEnumerable<T> source, Func<T, string> func)
        {
            var sb = new StringBuilder();
            foreach (var item in source)
            {
                sb.Append(func(item));
            }

            return sb.ToString();
        }
 
        /// <summary>
        /// 如果集合中不包含指定项，则添加该项
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="source">目标集合</param>
        /// <param name="item">要添加的项</param>
        /// <returns>如果添加成功返回true，如果项已存在返回false</returns>
        public static bool AddIfNotContains<T>([NotNull] this ICollection<T> source, T item)
        {
            Check.NotNullVoid(source, nameof(source));

            if (source.Contains(item))
            {
                return false;
            }

            source.Add(item);
            return true;
        }

 
        /// <summary>
        /// 批量添加集合中不存在的项
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="source">目标集合</param>
        /// <param name="items">要添加的项集合</param>
        /// <returns>实际添加的项集合</returns>
        public static IEnumerable<T> AddIfNotContains<T>([NotNull] this ICollection<T> source, IEnumerable<T> items)
        {
            Check.NotNullVoid(source, nameof(source));

            var addedItems = new List<T>();

            foreach (var item in items)
            {
                if (source.Contains(item))
                {
                    continue;
                }

                source.Add(item);
                addedItems.Add(item);
            }

            return addedItems;
        }

  
        /// <summary>
        /// 如果集合中不存在满足条件的项，则添加新项
        /// </summary>
        /// <typeparam name="T">集合元素类型</typeparam>
        /// <param name="source">目标集合</param>
        /// <param name="predicate">存在性检查条件</param>
        /// <param name="itemFactory">项创建函数</param>
        /// <returns>如果添加成功返回true，如果已存在满足条件的项返回false</returns>
        public static bool AddIfNotContains<T>([NotNull] this ICollection<T> source, [NotNull] Func<T, bool> predicate, [NotNull] Func<T> itemFactory)
        {
            Check.NotNullVoid(source, nameof(source));
            Check.NotNullVoid(predicate, nameof(predicate));
            Check.NotNullVoid(itemFactory, nameof(itemFactory));

            if (source.Any(predicate))
            {
                return false;
            }

            source.Add(itemFactory());
            return true;
        }

    }
}
